﻿using Application_Core.Bauteil_Component.Access_Layer;
using Application_Core.Bestellung_Component.Access_Layer.Exceptions;
using Application_Core.Bestellung_Component.Business_Logic_Layer;
using Application_Core.Bestellung_Component.Data_Access_Layer;
using Application_Core.Bestellung_Component.Data_Access_Layer.Implementations;
using Application_Core.Kunde_Component.Access_Layer;
using System;
using Utility.Global.Utilities;
using Utility.Persistence_Service;

namespace Application_Core.Bestellung_Component.Access_Layer
{
    public class BestellungComponentFacade : BestellungService
    {
        private readonly BestellungComponentBusinessLogic bestellungLogic;
        private readonly AngebotRepository angebotRepo;
        private readonly AuftragRepository auftragRepo;
        private readonly UnitOfWork unitOfWork;
        private readonly KundeInternalService kundeInternal;
        private readonly BauteilInternalService bauteilInternal;

        public BestellungComponentFacade(UnitOfWork unitOfWork, KundeInternalService kundeInternal, BauteilInternalService bauteilInternal)
        {
            this.unitOfWork = unitOfWork;
            this.kundeInternal = kundeInternal;
            this.bauteilInternal = bauteilInternal;
            this.bestellungLogic = new BestellungComponentBusinessLogicImpl(unitOfWork, kundeInternal, bauteilInternal);
            this.angebotRepo = new AngebotRepositoryImpl(unitOfWork);
            this.auftragRepo = new AuftragRepositoryImpl(unitOfWork);
        }

        public BestellungComponentFacade(UnitOfWork unitOfWork) :
            this(unitOfWork, new KundeComponentFacade(unitOfWork), new BauteilComponentFacade(unitOfWork)) { }

        public void CreateAngebot(AngebotDTO angebotDTO, int kundennummer, int bauteilnummer)
        {
            Check.Argument(angebotDTO != null, "DataTransferObjekt von Angebot wird benötigt.");
            Check.Argument(angebotDTO.Nummer > 0, "Angebotsnummer muss positiv sein.");
            Check.Argument(kundennummer > 0, "Kundennummer muss positiv sein.");
            Check.Argument(bauteilnummer > 0, "Bauteilnummer muss positiv sein.");
            Check.Argument(DateTime.Today.AddDays(-1).CompareTo(angebotDTO.GueltigAb) < 0, "GültigAb-Datum darf nicht in der Vergangenheit liegen.");
            Check.Argument(angebotDTO.Preis > 0, "Preis muss positiv sein.");

            Angebot angebot = angebotDTO.ToEntity();

            // Weitergabe an BusinessLogic (Benutzung von KundenInternalService und BauteilInternalService)
            this.bestellungLogic.CreateAngebot(angebot, kundennummer, bauteilnummer);
        }

        public void CreateAuftrag(int auftragsnummer, int angebotsnummer, int fertigungsauftragsnummer)
        {
            Check.Argument(auftragsnummer > 0, "Auftragsnummer muss positiv sein.");
            Check.Argument(angebotsnummer > 0, "Angebotsnummer muss positiv sein.");
            Check.Argument(fertigungsauftragsnummer > 0, "Fertigungsauftragsnummer muss positiv sein.");

            Angebot angebot = this.angebotRepo.FindByNummer(angebotsnummer);
            if (angebot == null)
            {
                throw new AngebotNotFoundException("Angebot mit Nummer " + angebotsnummer + " konnte nicht gefunden werden.");
            }

            // Weitergabe an BusinessLogic (Benutzung von BauteilInternalService)
            this.bestellungLogic.CreateAuftrag(angebot, auftragsnummer, fertigungsauftragsnummer);
        }

        public void DeleteAngebot(int angebotsnummer)
        {
            Check.Argument(angebotsnummer > 0, "Angebotsnummer muss positiv sein.");

            Angebot angebot = this.angebotRepo.FindByNummer(angebotsnummer);
            this.angebotRepo.Delete(angebot);
        }

        public void DeleteAuftrag(int auftragsnummer, int fertigungsauftragsnummer)
        {
            Check.Argument(auftragsnummer > 0, "Auftragsnummer muss positiv sein.");
            Check.Argument(fertigungsauftragsnummer > 0, "Fertigungsauftragsnummer muss positiv sein.");

            // Weitergabe an BusinessLogic (Benutzung von BauteilInternalService)
            this.bestellungLogic.DeleteAuftrag(auftragsnummer, fertigungsauftragsnummer);
        }
    }
}
